#include <iostream>
#include <unordered_map>
#include <string>
#include <memory>
#include <functional>
using namespace std;

class Product {
public:
	virtual void doSomeThing() {}
	virtual ~Product() = default;
};

class ProductA : public Product {
public:
	void doSomeThing() override {
		cout << "Product A" << endl;
	}
};

class ProductB : public Product {
public:
	void doSomeThing() override {
		cout << "Product B" << endl;
	}
};

class Factory {
public:
	using creator = std::function<std::unique_ptr<Product>()>;
	static void registryProduct(const string& name, creator c) {
		getRegistry()[name] = c;
	}
	
	static unique_ptr<Product> createProduct(const string& name) {
		unordered_map<string, creator>& registry = getRegistry();
		if (registry.find(name) == registry.end()) {
			return nullptr;
		}
		return registry[name]();
	}
private:
	static unordered_map<string, creator>& getRegistry() {
		static unordered_map<string, creator> registry;
		return registry;
	}
};


int main() {
	Factory::registryProduct("A", []() {return make_unique<ProductA>();});
	Factory::registryProduct("B", []() {return make_unique<ProductB>();});

	unique_ptr<Product> A = Factory::createProduct("A");
	unique_ptr<Product> B = Factory::createProduct("B");

	A->doSomeThing();
	B->doSomeThing();

	return 0;
}

